/*
 * @(#)CompositeBOMethod.java $version 2010. 8. 11
 *
 * Copyright 2007-2010 NHN Corp. All rights Reserved. 
 * NHN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.nhncorp.usf.macro.method.component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import freemarker.template.*;

/**
 * @author Web Platform Development Team
 */
public class CompositeBOMethod implements TemplateMethodModelEx {

    /**
     * @param args the arguments
     * @return the result bo list
     * @throws TemplateModelException the TemplateModelException
     */
    @SuppressWarnings("unchecked")
    public Object exec(List args) throws TemplateModelException {
        List resultBOs = new ArrayList();

        if (args.size() != 4) {
            throw new IllegalArgumentException();
        }

        List sourceBOList = getAsList(args.get(0));
        List targetBOList = getAsList(args.get(1));
        String foreignKey = getAsString(args.get(2));
        List mergeColumns = getAsList(args.get(3));

        if (sourceBOList != null) {

            for (Object aSourceBO : sourceBOList) {
                HashMap sourceBO = (HashMap)aSourceBO;

                if (sourceBO.containsKey(foreignKey)) {
                    String targetPK = (String)sourceBO.get(foreignKey); // foreignKey

                    if (targetBOList != null) {

                        for (Object aTargetBO : targetBOList) {
                            HashMap targetBO = (HashMap)aTargetBO;

                            if (targetBO.containsKey(foreignKey)) {
                                String key = (String)targetBO.get(foreignKey);

                                if (key.equals(targetPK)) {
                                    merge(mergeColumns, foreignKey, sourceBO, targetBO);
                                }

                            }

                        }

                    }

                }

                resultBOs.add(sourceBO);
            }

        }

        return resultBOs;
    }

    /**
     * Merge.
     *
     * @param mergeColumns the merge columns
     * @param foreignKey   the foreign key
     * @param sourceBO     the source bo
     * @param targetBO     the target bo
     */
    @SuppressWarnings("unchecked")
	private void merge(List mergeColumns, String foreignKey, HashMap sourceBO, HashMap targetBO) {
        if (mergeColumns == null) {

            for (Object obj : targetBO.keySet()) {
                String targetKey = (String)obj;

                if (!targetKey.equals(foreignKey)) {
                    sourceBO.put(targetKey, targetBO.get(targetKey));
                }

            }

        } else {
            for (Object mergeColumnName : mergeColumns) {
                if (targetBO.containsKey(mergeColumnName)) {
                    String mergeColumnValue = (String)targetBO.get(mergeColumnName);
                    sourceBO.put(mergeColumnName, mergeColumnValue);
                }
            }
        }
    }

    /**
     * Gets the as string.
     *
     * @param object the object
     * @return the as string
     * @throws TemplateModelException the template model exception
     */
    private String getAsString(Object object) throws TemplateModelException {
        if (object == null) {
            return null;
        } else if (object instanceof TemplateScalarModel) {
            return ((TemplateScalarModel)object).getAsString();
        }

        return null;
    }

    /**
     * Gets the as list.
     *
     * @param object the object
     * @return the as list
     * @throws TemplateModelException the template model exception
     */
    @SuppressWarnings("unchecked")
	private List getAsList(Object object) throws TemplateModelException {
        if (object == null) {
            return null;
        } else if (object instanceof SimpleSequence) {
            return ((SimpleSequence)object).toList();
        } else if (object instanceof TemplateCollectionModel) {
            return (new SimpleSequence((TemplateCollectionModel)object)).toList();
        }

        return null;
    }
}
